package com.jl.core.netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class NettyServer implements CommandLineRunner {


    private static final int port = 8888;

    public void start() throws Exception{
        EventLoopGroup bossGroup = new NioEventLoopGroup(8);

        EventLoopGroup group = new NioEventLoopGroup();

        try {
            ServerBootstrap sb = new ServerBootstrap();
            sb.option(ChannelOption.SO_BACKLOG,1024);
            sb.option(ChannelOption.AUTO_READ,true);
            sb.childOption(ChannelOption.SO_KEEPALIVE,true);
            sb.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 60);
            sb.group(group,bossGroup)//绑定线程池
                    .channel(NioServerSocketChannel.class)//指定使用的channel
                    .localAddress(port)//绑定监听端口
                    .childHandler(new ChannelInitializer<SocketChannel>() {

                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            log.info("收到新连接");
                            //心跳检测
                            ch.pipeline().addLast(new IdleStateHandler(30, 30, 30));
                            ch.pipeline().addLast(new HttpServerCodec());
                            //以块的方式来写处理器
                            ch.pipeline().addLast(new ChunkedWriteHandler());
                            ch.pipeline().addLast(new HttpObjectAggregator(8192));
                            ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws",null,true,65536*10));
                            ch.pipeline().addLast(new MyWebSocketHandler());
                        }

                    });
            //服务器异步创建绑定
            ChannelFuture cf = sb.bind().sync();
            log.info(NettyServer.class+" 启动正在监听： "+cf.channel().localAddress());
            //关闭服务器通道
            cf.channel().closeFuture().sync();
        }catch (Exception ex){
            ex.printStackTrace();
        }finally {
            group.shutdownGracefully().sync();
            bossGroup.shutdownGracefully().sync();
            log.info("断开了啊啊啊!!!!!!!!!!!!!!");
        }
    }

    @Override
    public void run(String... args) throws Exception {
        new NettyServer().start();
    }

}
